<?php

namespace app\admin\controller\health;

use app\common\controller\Backend;
use app\common\model\Area;
use app\health\model\HealthOrder;
use app\health\model\healthPro\Channel;
use app\health\model\healthPro\TvService;
use app\health\model\HealthUser;
use app\health\model\HealthUserChannel;
use app\health\model\statistics\HealthStatistics;
use app\health\model\tracking\HealthTrackingHealth;
use app\health\model\tracking\HealthTrackingUserRemain;
use app\health\service\PajkService;
use think\Cache;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\exception\DbException;
use think\wenhainan\Thinkcsv;

class Dashboard extends Backend
{
    public function index()
    {
        $default_date = [date('Y-m-d', strtotime('-1 week')), date('Y-m-d')];
        if ($this->request->isAjax()) {
            $params          = $this->request->param();
            $date            = $params['date'] ?? $default_date;
            $starDate        = strtotime($date[0]);
            $endDate         = strtotime($date[1]);
            $activeUserTotal = 0;
            while ($starDate <= $endDate) {
                $activeUserTotal += Cache::store('redis')->handler()->bitcount('health_user:active:' . date('Y-m-d', $starDate));
                $starDate        = strtotime('+1 day', $starDate);
            }
            $date[0]                                      .= ' 00:00:00';
            $date[1]                                      .= ' 23:59:59';
            $dashboard                                    = [];
            $dashboard['statistics']['user_total']        = HealthUser::count();
            $dashboard['statistics']['new_user_total']    = HealthUser::whereTime('created_at', 'between', $date)->count();
            $dashboard['statistics']['active_user_total'] = $activeUserTotal;
            $dashboard['statistics']['order_amount_sum']  = HealthOrder::where('pay_status', '2')->whereTime('pay_time', 'between', $date)->sum('pay_price');
            $userRemain                                   = HealthTrackingUserRemain::column('id,day', 'user_id');
            $dashboard['area_user']                       = HealthUserChannel::whereTime('register_date', 'between', $date)
                ->field('province,city,count(*) as number,GROUP_CONCAT(user_id) as user_ids')
                ->group('city_cde')
                ->order('number', 'desc')
                ->limit(5)
                ->select();
            foreach ($dashboard['area_user'] as &$areaUser) {
                $user_ids                 = explode(',', $areaUser['user_ids']);
                $areaUser['active_total'] = 0;
                foreach ($user_ids as $userId) {
                    isset($userRemain[$userId]) && $areaUser['active_total'] += 1;
                }
            }
            $twoRemain   = 0;
            $threeRemain = 0;
            $sevenRemain = 0;
            foreach ($userRemain as $remain) {
                switch ($remain['day']) {
                    case 2:
                        ++$twoRemain;
                        break;
                    case 3:
                        ++$threeRemain;
                        break;
                    case 7:
                        ++$sevenRemain;
                        break;
                }
            }
            $dashboard['user_remain'] = [
                ['name' => '新增用户', 'number' => $dashboard['statistics']['user_total']],
                ['name' => '次日留存', 'number' => $twoRemain],
                ['name' => '三日留存', 'number' => $threeRemain],
                ['name' => '七日留存', 'number' => $sevenRemain],
            ];
            $channel                  = [];
            $channelUser              = HealthUserChannel::whereTime('register_date', 'between', $date)
                ->with(['popularize'])
                ->select();
            foreach ($channelUser as $item) {
                if ($item['channel_id'] > 0) {
                    if (isset($channel[$item['channel_id']])) {
                        $channel[$item['channel_id']]['number'] += 1;
                    } else {
                        $channel[$item['channel_id']] = [
                            'name'   => $item['popularize']['name'] ?: $item['popularize']['zf_code'],
                            'number' => 1
                        ];
                    }
                } else if (config('wxapp_scene.' . $item['scene'])) {
                    if (isset($channel['wxapp_' . $item['scene']])) {
                        $channel['wxapp_' . $item['scene']]['number'] += 1;
                    } else {
                        $channel['wxapp_' . $item['scene']] = [
                            'name'   => config('wxapp_scene.' . $item['scene']) ?: $item['scene'],
                            'number' => 1
                        ];
                    }
                } else if (isset($channel['other'])) {
                    $channel['other']['number'] += 1;
                } else {
                    $channel['other'] = [
                        'name'   => '其它',
                        'number' => 1
                    ];
                }
            }
            sort($channel);
            $dashboard['user_channel']    = $channel;
            $dashboard['health_tracking'] = $this->getHealthTracking($date);
            $this->success('success', '', $dashboard);
        }
        $dashboard               = [];
        $dashboard['user_total'] = HealthUser::count();
        $this->assignconfig(compact('dashboard', 'default_date'));
        return $this->view->fetch();
    }


    /**
     * 获取健康服务点击统计
     * @param $date
     * @return array
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    private function getHealthTracking($date): array
    {
        $data    = HealthTrackingHealth::whereTime('created_at', 'between', $date)
            ->field('type,count(type) as total')
            ->group('type')
            ->select();
        $data    = collection($data)->toArray();
        $typeMap = [];
        foreach (collection(PajkService::serviceList())->toArray() as $item) {
            $typeMap[$item['type']] = $item;
        }
        foreach ($data as &$datum) {
            $datum['type_name'] = isset($typeMap[$datum['type']]) ? $typeMap[$datum['type']]['name'] : '-';
        }
        return $data;
    }


    /**
     * 数据统计
     * @throws DbException
     * @throws Exception
     */
    public function statistics()
    {
        $params = $this->request->param();
        if ($this->request->isAjax() || (!empty($params['action']) && $params['action'] === 'export')) {
            $action = $params['action'] ?? 'table';
            $where  = [];
            if (!empty($params['province_id'])) {
                $where['province_id'] = ['in', $params['province_id']];
            }
            if (!empty($params['channel_id'])) {
                $where['channel_id'] = ['in', $params['channel_id']];
            }
            if (!empty($params['day'])) {
                $where['day'] = ['between time', $params['day']];
            }
            $data = [];
            if ($action === 'table') {
                $limit    = $this->request->param('limit', 10);
                $paginate = HealthStatistics::where($where)
                    ->field([
                        "day",
                        "sum(new_user) as new_user",
                        "sum(active_user) as active_user",
                        "sum(active_user_previous) as active_user_previous",
                        "sum(sign_in_user) as sign_in_user",
                        "sum(authentication_user) as authentication_user",
                        "sum(health_click) as health_click",
                        "sum(health_people) as health_people",
                        "sum(evaluation_click) as evaluation_click",
                        "sum(evaluation_people) as evaluation_people",
                        "sum(goods_click) as goods_click",
                        "sum(goods_people) as goods_people",
                    ])
                    ->group('day')
                    ->order('id', 'desc')
                    ->paginate($limit);
                $lists    = [];
                foreach ($paginate->items() as $item) {
                    $lists[] = [
                        'day'                  => $item['day'],
                        'new_user'             => $item['new_user'],
                        'active_user'          => $item['active_user'],
                        'active_user_previous' => $item['active_user_previous'],
                        'sign_in_user'         => $item['sign_in_user'],
                        'authentication_user'  => $item['authentication_user'],
                        'health_click'         => $item['health_click'],
                        'health_people'        => $item['health_people'],
                        'evaluation_click'     => $item['evaluation_click'],
                        'evaluation_people'    => $item['evaluation_people'],
                        'goods_click'          => $item['goods_click'],
                        'goods_people'         => $item['goods_people'],
                    ];
                }
                $data['rows']       = $lists;
                $data['statistics'] = HealthStatistics::where($where)
                    ->field([
                        "sum(new_user) as new_user",
                        "sum(active_user_previous) as active_user_previous",
                        "sum(sign_in_user) as sign_in_user",
                        "sum(authentication_user) as authentication_user",
                        "sum(health_click) as health_click",
                        "sum(health_people) as health_people",
                        "sum(evaluation_click) as evaluation_click",
                        "sum(evaluation_people) as evaluation_people",
                        "sum(goods_click) as goods_click",
                        "sum(goods_people) as goods_people",
                    ])->find();
                $data['total']      = $paginate->total();
            }
            if ($action === 'export') {
                $paginate = HealthStatistics::where($where)
                    ->field([
                        "day",
                        "sum(new_user) as new_user",
                        "sum(active_user) as active_user",
                        "sum(active_user_previous) as active_user_previous",
                        "sum(sign_in_user) as sign_in_user",
                        "sum(authentication_user) as authentication_user",
                        "sum(health_click) as health_click",
                        "sum(health_people) as health_people",
                        "sum(evaluation_click) as evaluation_click",
                        "sum(evaluation_people) as evaluation_people",
                        "sum(goods_click) as goods_click",
                        "sum(goods_people) as goods_people",
                    ])
                    ->group('day')
                    ->order('id', 'desc')
                    ->select();
                $lists    = [];
                foreach ($paginate as $item) {
                    $lists[] = [
                        'day'                  => $item['day'],
                        'new_user'             => $item['new_user'],
                        'active_user_previous' => $item['active_user_previous'],
                        'sign_in_user'         => $item['sign_in_user'],
                        'authentication_user'  => $item['authentication_user'],
                        'health_click'         => $item['health_click'],
                        'health_people'        => $item['health_people'],
                        'evaluation_click'     => $item['evaluation_click'],
                        'evaluation_people'    => $item['evaluation_people'],
                        'goods_click'          => $item['goods_click'],
                        'goods_people'         => $item['goods_people'],
                    ];
                }
                //浏览器渲染导出csv
                $header = ['日期', '新增用户', '活跃用户', '签到用户', '实名认证', '健康服务点击次数', '健康服务点击人数', '测评点击次数', '测评点击人数', '商品点击次数', '商品点击人数'];
                //浏览器访问渲染下载
                $csv = new Thinkcsv('统计记录-' . date('YmdHis') . '.csv', $header, $lists);
                $csv->export();
            }
            if ($action === 'bar') {
                $result = HealthStatistics::where($where)
                    ->field([
                        "sum(new_user) as new_user",
                        "sum(active_user) as active_user",
                        "sum(active_user_previous) as active_user_previous",
                        "sum(sign_in_user) as sign_in_user",
                        "sum(authentication_user) as authentication_user",
                        "sum(health_click) as health_click",
                        "sum(health_people) as health_people",
                        "sum(evaluation_click) as evaluation_click",
                        "sum(evaluation_people) as evaluation_people",
                        "sum(goods_click) as goods_click",
                        "sum(goods_people) as goods_people",
                    ])
                    ->order('id', 'desc')
                    ->find();
                $data   = [
                    ['label' => '新增用户', 'value' => (int)($result['new_user'] ?? 0)],
                    ['label' => '活跃用户', 'value' => (int)($result['active_user'] ?? 0)],
                    ['label' => '实名用户', 'value' => (int)($result['authentication_user'] ?? 0)],
                    ['label' => '签到用户', 'value' => (int)($result['sign_in_user'] ?? 0)],
                    ['label' => '健康服务点击次数', 'value' => (int)($result['health_click'] ?? 0)],
                    ['label' => '健康服务点击人数', 'value' => (int)($result['health_people'] ?? 0)],
                    ['label' => '测评点击次数', 'value' => (int)($result['evaluation_click'] ?? 0)],
                    ['label' => '测评点击人数', 'value' => $result['evaluation_people'] ?? 0],
                    ['label' => '商品点击次数', 'value' => $result['goods_click'] ?? 0],
                    ['label' => '商品点击人数', 'value' => $result['goods_people'] ?? 0],
                ];
            }
            $this->success('数据统计', null, $data);
        }
        $province = Area::where('level', 1)->column('id,shortname,name');
        sort($province);
        $channel = Channel::all();
        $this->assignconfig(compact('province', 'channel'));
        $this->assign('title', '数据统计');
        return $this->view->fetch();
    }
}
